#include <cstdio>
#include <vector>
#include <functional>
#include <algorithm>
using namespace std;

struct Node;
struct Edge
{
	Node* from;
	Node* to;
	int cost;
	Edge* next;
	
	Edge( Node* f, Node* t, int c ): from(f), to(t), cost(c)
	{
		next = NULL;
	}
	
	bool operator< ( const Edge& edge ) const
	{
		return cost < edge.cost;
	}
};

struct Node
{
	Edge* first;
	Node* parent;
	int id;
	
	Node()
	{
		id = -1;
		first = NULL;
		parent = NULL;
	}
};

Node* findroot( Node* p )
{
	if( p->parent == p ) return p;
	else return findroot( p->parent );
}

int main()
{
	int nodec = 0, edgec = 0;
	scanf( "%d %d", &nodec, &edgec );
	
	vector<Node> nodes( nodec );
	vector<Edge> edges;
	vector<Edge> MSTedges;
	
	for( int i = 0; i < nodec; i++ )
	{
		nodes[i].id = i;
		nodes[i].parent = &nodes[i];
	}
	for( int i = 0; i < edgec; i++ )
	{
		int u = 0, v = 0, c = 0;
		scanf( "%d %d %d", &u, &v, &c );
	
		Edge ed1( &nodes[u], &nodes[v], c );
		Edge ed2( &nodes[u], &nodes[v], c );
		
		Node& nu = nodes[u];
		ed1.next = nu.first;
		edges.push_back( ed1 );
		nu.first = &edges[ edges.size() - 1 ];
		
		Node& nv = nodes[v];
		ed2.next = nv.first;
		edges.push_back( ed2 );
		nv.first = &edges[ edges.size() - 1 ];
	}
	
	sort( edges.begin(), edges.end() );
	
	for( vector<Edge>::iterator it = edges.begin(); it != edges.end(); it++ )
	{
		Edge& edge = *it;
		
		Node* up = findroot(edge.from);
		Node* vp = findroot(edge.to);
		
		if( up == vp ) continue;
		
		vp->parent = up;
		MSTedges.push_back( edge );
	}
	
	for( vector<Edge>::const_iterator it = MSTedges.begin(); it != MSTedges.end(); it++ )
	{
		const Edge& edge = *it;
		
		printf( "%d -> %d, %d\n", edge.from->id, edge.to->id, edge.cost );
	}
	
	return 0;
}
